package com.techwells.taco.dataaccess;

import java.util.concurrent.locks.ReentrantLock;

import android.annotation.SuppressLint;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.techwells.taco.utils.LogUtil;

public class DataBaseHelper {
	private static DataBaseHelper dbHelper = null;
	//mLock is used for lock threads which want's to write database
	private static ReentrantLock mLock = new ReentrantLock();
	//readHelper store a SQLiteOpenHelper for read SQLite database(do select)
	private ThreadLocal<SQLiteOpenHelper> readHelper = new ThreadLocal<SQLiteOpenHelper>();
	//writeHelper store a SQLiteOpenHelper for write SQLite database(do insert,update,delete...)
	private ThreadLocal<SQLiteOpenHelper> writeHelper = new ThreadLocal<SQLiteOpenHelper>();
	
	private Context appContext = null;
	private String databaseName = null;
	private int databaseVersion = 0;

	/**
	 * 构造函数
	 * 
	 * @param context 上下文
	 * @param dbName 数据库名
	 * @param dbVersion 数据库版本号
	 */
	public DataBaseHelper(Context context, String dbName, int dbVersion) {
		appContext = context;
		databaseName = dbName;
		databaseVersion = dbVersion;
	}
	
	/**
	 * 数据库操作单例，调用方法如下：
	 * DataBaseHelper helper = DataBaseHelper.shareInstance(applicationContext, "数据库名称", 1.0);
	 * helper.getWriteConnection();
	 * helper.close();
	 * 
	 * @param context 上下文
	 * @param dbName 数据库名
	 * @param dbVersion 数据库版本号
	 * @return	数据库操作单例对象
	 */
	public synchronized static DataBaseHelper shareInstance(Context context, String dbName, int dbVersion) {
		if (dbHelper == null) {
			dbHelper = new DataBaseHelper(context, dbName, dbVersion);
		}
		return dbHelper;
	}

	/** 
	 * 获得和数据库的连接对象，通过该连接可以访问数据库执行相关数据库操作
	 * getWritableDatabase和getReadableDatabase会自动创建数据库打开并获取其引用
	 */
	public SQLiteDatabase getReadConnection() {
		SQLiteOpenHelper helper = readHelper.get();
		SQLiteDatabase connection = null;
		try {
			if (helper == null) {
				helper = new SQLiteOpenHelper(appContext,databaseName,null,databaseVersion) {
					
					@Override
					public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onCreate(SQLiteDatabase db) {
						// TODO Auto-generated method stub
						
					}
				};		
				readHelper.set(helper);
			}
			connection = helper.getReadableDatabase();
		} catch (Exception e) {
			e.printStackTrace();
			LogUtil.e("dbLog", "readConnection error");
		}
		return connection;
	}

	@SuppressLint("NewApi") public SQLiteDatabase getWriteConnection() {
		//write helper should locked for thread safe
		mLock.lock();
		SQLiteOpenHelper helper = writeHelper.get();
		SQLiteDatabase connection = null;
		try {
			if (helper == null) {
				helper = new SQLiteOpenHelper(appContext,databaseName,null,databaseVersion) {
					
					@Override
					public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void onCreate(SQLiteDatabase db) {
						// TODO Auto-generated method stub
						
					}
				};		
				writeHelper.set(helper);
			}
			connection = helper.getWritableDatabase();
			//set WAL mode to allow mutiThread
			connection.enableWriteAheadLogging();
		} catch (Exception e) {
			e.printStackTrace();
			LogUtil.e("dbLog", "writeConnection error");
		}
		return connection;
	}
	
	/**
	 * 关闭数据库，用完后必须调用该方法关闭数据库连接
	 */
	public void close() {
		SQLiteOpenHelper writeConn = writeHelper.get();
		SQLiteOpenHelper readConn = readHelper.get();
		//close SQLiteOpenHelper if you never use it
		if (writeConn != null) {
			writeConn.close();
			LogUtil.e("dbLog", "write connection "+writeConn.hashCode()+" closed");
			//if close a write helper,unlock the thread
			if(mLock.isLocked()) {
				try {
					mLock.unlock();
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		if (readConn != null) {
			readConn.close();
			LogUtil.e("dbLog", "read connection "+readConn.hashCode()+" closed");
		}
		
	}
}
